#! -*- coding: utf-8 -*-
import json

from flask import request, current_app
from mongoengine import Q
from werkzeug.utils import MultiDict

from app.constants import DEVICE_TYPES
from app.models import UserDeviceToken, DeviceToken
from app.third_party_api import btapi
from app.utils import (
    get_access_token, api_error, wrap_response,
    compressed_dict, trim, safe_int
)


@current_app.route('/vacation/bdchannel/get_access_token/', methods=['GET'])
def retrieve_access_token():
    """
    从baidu channel获取access_token后返回android

    #### 请求参数

    无

    #### 返回结果

        {
            "access_token": "3.5cfa2576b159ab8c2b24d6708451033d.2592000.1355637435.282335-299250",
            "expires_in": 2592000,
            "refresh_token": "4.1bb64ad6b59189b8a7d1e0e1ec899d88.315360000.1668405435.282335-299250"
        }

    #### 参数说明

    expires_in表示该access_token的有效时间，单位为秒

    """
    try:
        access_token = get_access_token(
            current_app.config['VACATION_BAIDU_API_KEY'],
            current_app.config['VACATION_BAIDU_API_SECRET']
        )
    except:
        return api_error(41012)

    access_token = compressed_dict(
        access_token,
        ('access_token', 'expires_in', 'refresh_token')
    )

    return wrap_response(access_token)


@current_app.route('/vacation/bdchannel/user_id/add/', methods=['POST'])
def add_user_id():
    """
    添加百度channel的user_id，用来接收推送消息

    #### 请求参数

    参数名 | 必选 | 类型及范围 | 说明
    ---- | ---- | ---- | ----
    user_id | Y | string | APP端调用百度channel获得的user_id

    #### 返回结果

        {}

    """
    if request.form:
        getter = request.form.get
    else:
        getter = MultiDict(request.json(force=True)).get

    value = trim(getter('user_id', ''))
    if not value or not request.user.is_authenticated():
        raise api_error(41006)

    token = value
    device_type = DEVICE_TYPES.VACATION_BAIDU_CHANNEL
    btapi.update_user_device_tokne(
        DEVICE_TYPES.VACATION_BAIDU_CHANNEL,
        value,
    )
    # 同一个token应该只能为一个用户所用，所以删除旧的token和用户之间的关联
    condition = Q(device=device_type, token=value)
    user_device_token = UserDeviceToken.objects.filter(condition).first()
    if user_device_token:
        user_device_token.is_active = False
        user_device_token.save()

    # 添加新的对应关系
    created = False
    query_condition = Q(
        user_id=request.user.id,
        device=device_type,
        token=value
    )
    query_obj = UserDeviceToken.objects.filter(query_condition).first()
    if not query_obj:
        data = dict(
            user_id=request.user.id,
            device=device_type,
            token=value,
            is_active=True
        )
        UserDeviceToken.objects.create(**data)
        created = True

    if created:
        # Update baidu channel tag
        # tasks.vacation_update_baidu_channel_tags.delay(request.user)
        # Remove anoymous unregistered tag
        # tasks.vacation_update_baidu_channel_tag_by_buser_id.delay(token,
        #         settings.BAIDU_CHANNEL_TAG_ANOYMOUS_UNREGISTERED, remove=True)
        pass
    return wrap_response({})


@current_app.route('/vacation/bdchannel/add_channel_user_id/', methods=['POST'])
def add_channel_user_id():
    """
    记录用户的channel user_id,无需登录

    #### 请求参数

    参数名 | 必选 | 类型及范围 | 说明
    ---- | ---- | ---- | ----
    user_id | Y | string | baidu channel的user_id

    #### 返回结果

        {}
    """
    if request.form:
        getter = request.form.get
    else:
        getter = MultiDict(request.json(force=True)).get

    token = trim(getter('user_id', ''))
    if not token:
        return api_error(41006)

    created = False
    value = 'vacation%s' % token
    device_type = DEVICE_TYPES.VACATION_BAIDU_CHANNEL
    query_condition = Q(device_token=value, device=device_type)
    query_obj = DeviceToken.objects.filter(query_condition).first()
    if not query_obj:
        data = dict(
            device_token=value,
            device=device_type
        )
        DeviceToken.objects.create(**data)
        created = True

    if created:
        # tasks.vacation_update_baidu_channel_tag_by_buser_id.delay(token,
        #         settings.BAIDU_CHANNEL_TAG_SYSTEM_AD)
        # tasks.vacation_update_baidu_channel_tag_by_buser_id.delay(token,
        #         settings.BAIDU_CHANNEL_TAG_ANOYMOUS_UNREGISTERED)
        pass
    return {}


@current_app.route('/vacation/ios/add_device_token/', methods=['POST'])
def add_device_token():
    """
    添加device token，用来接收推送消息(IOS专用)

    #### 请求参数

    参数名 | 必选 | 类型及范围 | 说明
    ---- | ---- | ---- | ----
    token | Y | string | device token，用来接收推送消息。

    #### 返回结果

        {}
    """
    if request.form:
        formdata = request.form
    else:
        formdata = MultiDict(request.json(force=True))

    if 'token' not in formdata:
        return api_error(40095)

    token = trim(formdata.get('token', ''))
    if len(token) != 64:
        return api_error(40095)

    # Old, Do not store this token is UserProfile now
    # profile = request.user.get_profile()
    # profile.device_token = token
    # profile.save()

    device_type = DEVICE_TYPES.VACATION_IOS_DEVICE_TOKEN
    token = 'vacation%s' % token

    if request.user.is_authenticated():
        condition = Q(device=device_type, token=token)
        user_device_token = UserDeviceToken.objects.filter(condition).first()
        if user_device_token:
            user_device_token.is_active = False
            user_device_token.save()

        data = dict(
            user=request.user,
            device=device_type,
            token=token
        )
        query_condition = Q(
            user=request.user,
            device=device_type,
            token=token
        )
    else:
        data = dict(
            device=device_type,
            device_token=token
        )
        query_condition = Q(
            device=device_type,
            token=token
        )

    created = False
    query_obj = DeviceToken.objects.filter(query_condition).first()
    if not query_obj:
        obj = DeviceToken.objects.create(**data)
        created = True

    if not created:
        obj.is_active = True
        obj.save()

    return wrap_response({})


@current_app.route('/vacation/push/', methods=['POST'])
def push_message():
    """
    [REST] 自由行推送
    #### 请求参数

    参数名 | 必须 | 类型 | 说明
    ---- | ---- | ---- | ----
    user_id | Y | int | 用户id, 加密
    params | Y | str | key-value的json数据

    #### params 参数说明
    {
        'msg': 'hello world',      // 客户端通知里的内容, 必需
        'is_dialog': True,         // 是否是问答消息,
        'mtu_id': 34456,           // mtu_id 非加密, 非必需
        'hotel_id': 34532,         // hotel_id 非必需
    }

    * is_dialog为True时，mtu_id, hotel_id 必须有一个且不能同时存在

    #### 返回结果
    {
        'status': 0,
        'message': 'success',
    }
    """
    if request.form:
        getter = request.form.get
    else:
        getter = MultiDict(request.json(force=True))

    user_id = safe_int(getter('user_id'))
    params = trim(getter('params'))

    ret = {
        'status': 49999,
    }

    try:
        params = json.loads(params)
        if not isinstance(params, dict):
            ret['message'] = u'params不是一个key-value的数据'
            return wrap_response(ret)
    except:
        ret['message'] = u'params不是个json数据'
        return wrap_response(ret)

    if 'msg' not in params:
        ret['message'] = u'params参数里的msg是必需项'

    if params.get('dialog') and not params.get('mtu_id') and \
            not params.get('hotel_id'):
        ret['message'] = u'问答消息推送mtu_id和hotel_id必需有一个'
    if params.get('dialog') and params.get('mtu_id') and \
            params.get('hotel_id'):
        ret['message'] = u'问答消息推送mtu_id和hotel_id不能同时存在'

    if 'message' in ret:
        return wrap_response(ret)

    params['alert'] = params['msg']
    # tasks.send_vacation_ios_push.delay([user_id], params)
    # tasks.send_vacation_android_push.delay([user_id], params)
    # tasks
    data = {
        'status': 0,
        'message': 'success',
    }
    return wrap_response(data)
